/**
 *
 * © Bahadir Zeren 2011
 * bzeren@gmail.com
 * No warranties, express or implied, are made for this program.
 *
 */

package org.baatar.remoting.service;

import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.baatar.net.message.IRequest;
import org.baatar.net.message.IResponse;
import org.baatar.net.tcp.IMessageProcessor;
import org.baatar.remoting.message.RemoteResponse;
import org.baatar.remoting.message.RemoteRequest;

/**
 * Message processor class works between TCP service and remoting implementor.
 * Instances of this object receives requests from TCP service objects and pass
 * to implementor object. After processing the message it returns response
 * message to TCP service.
 * 
 * @see TCPService
 * @see IImplementor
 * 
 * @author B_ZEREN
 */
public class ImplementorTCPBridge implements IMessageProcessor {

    private IImplementor implementor = null;
    private Class implementorClass = null;

    /**
     * Constructor of the bridge class.
     * 
     * @param implementor object which will process messages.
     * @throws Exception if an exception occurs.
     */

    public ImplementorTCPBridge(IImplementor implementor) throws Exception {
        this.implementor = implementor;
        this.implementorClass = implementor.getClass();
    }

    /**
     * The method which passes the requests coming from TCP service to 
     * implementor object and returns the response message back.
     * 
     * @param clientIP IP number of the client.
     * @param clientPortNr port number of the client.
     * @param request request message.
     * @param logger logger to log processing steps and exceptions.
     * @return IResponse appropriate response message of the request object.
     * @throws Exception if an exception occurs while processing the request.
     */
    @Override
    public IResponse processMessage(String clientIP,
                                    int clientPortNr,
                                    IRequest request,
                                    Logger logger) throws Exception {
        Object res = null;

        RemoteRequest remoteRequest = null;

        try  {

            remoteRequest = (RemoteRequest) request;

            int paramsSize = remoteRequest.getParams().size();

            Class[] argTypes = new Class[paramsSize];
            Object[] args = new Object[paramsSize];

//            StringBuilder sb = new StringBuilder();
//
//            sb.append(remoteRequest.getClientInfo());
//            sb.append("-");
//            sb.append(clientIP);
//            sb.append(":");
//            sb.append(clientPortNr);
//            sb.append(" : ");
//
//            sb.append(remoteRequest.getOperation());
//
//            String clientInfoStr = sb.toString();
//
//            sb.append("(");

            for (int i = 0; i < paramsSize; i++) {
                argTypes[i] = remoteRequest.getParams().get(i).getClass();
                args[i] = remoteRequest.getParams().get(i);

//                if (i > 0)
//                    sb.append(", ");
//                sb.append(args[i]);
            }

//            sb.append(")");
//
//            logger.debug(sb.toString());

            Method mainMethod = implementorClass.getDeclaredMethod(remoteRequest.getOperation(), argTypes);

            res = (Object) mainMethod.invoke(implementor, args);

//            logger.debug(clientInfoStr + " return " + res);

            return new RemoteResponse(res);

        } catch(Exception ex) {
            if (remoteRequest == null)
                logger.error("Exception " + ex.getMessage());
            else
                logger.error(remoteRequest.getOperation() + " exception " + ex.getMessage());

            return new RemoteResponse(ex);
        }
    }
}
